基于frp构建内网穿透
开篇废话
第一次接触到内网穿透这一概念大概是20017年左右,手中有一树莓派,想到如何能够在公司访问运行在家里的树莓派呢?百度之,基本就是下面这种情况——广告劝退,我一个小小的需求,要什么花里胡哨的东西,当时不了了之。后来了解到NATAPP,使用方便,价格也不贵,关键是配置简单,还支持自定义二级域名(当然是要钱的啦),这样使用了很长一段时间。但后来发现自己的使用场景是希望长期处于内网穿透,偶尔用一下,频率相当低。即使使用NATAPP这样低至9元/月的服务都嫌贵。
无疑,开源软件是拯救我的唯一方式。gayhub是个好地方。goproxy(8k star)和frp(33k star)映入眼帘。大致查看了使用教程,无论从简易程度,还是受欢迎程度,我都倾向于选择frp。它通过命令行配置。别跟我整那些花里胡哨的dashboard,简单易用才是硬道理,我不需要复杂的功能。
frp简介
frp使用go语言编写,工作原理是反向代理,下面的官方的架构图。
需要说明的是,该项目目前处于开发状态,未经充分测试和验证,因此不推荐用于生产环境。
关于使用frp的前置条件,是你需要有一台VPS,我手里有一台阿里云服务器,正好。
需求说明
自己目前有两个需求
- 可通过公网IP ssh到树莓派进行操作
- 可通过域名访问运行在树莓派上的web服务,端口7000。暂时只要http
下面针对这两个需求进行配置
服务端
frp配置
到项目的release页下载符合自己服务器版本的压缩包。
我的VPS是ubuntu 64位,因此下载frp_0.31.2_linux_amd64.tar.gz。 依照如下步骤
解压
1
tar -zxvf frp_0.31.2_linux_amd64.tar.gz
修改ini配置文件
修改目录下的服务器配置文件frps.ini,注意别改到客户端配置文件frpc.ini。
这里指定了frp的tcp服务监听7000端口,http服务监听7001端口。
1
2
3
4# frps.ini
[common]
bind_port = 7000
vhost_http_port = 7001启动
1
./frps -c ./frps.ini
看到如下输出,代表成功了。
1
2
32020/02/23 19:09:37 [I] [service.go:152] frps tcp listen on 0.0.0.0:7000
2020/02/23 19:09:37 [I] [service.go:194] http service listen on 0.0.0.0:7001
2020/02/23 19:09:37 [I] [root.go:205] start frps success
nginx配置
第二点需求可以通过nginx实现,直接在80端口上监听,将对应域名转发到该域名下7001端口。
1 | server { |
客户端
frp将客户端和服务端文件放在一个包中,你可以观察到上面解压出来的包中包含了frpc——即客户端命令和配置文件。因此,如果客户端环境也是linux 64位,可以直接使用刚才下载的那个包。
但我的客户端是树莓派,因此需要下载arm 32位版,即frp_0.31.2_linux_arm.tar.gz,注意不要下载64位,树莓派3使用了64位CPU,但操作系统依然是32位。
执行如下步骤
解压
1
tar -zxvf frp_0.31.2_linux_arm.tar.gz
修改配置文件
修改frpc.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# frpc.ini
# 这里填写服务端的IP和端口号
[common]
server_addr = x.x.x.x
server_port = 7000
# 将服务端的6000端口转发到本地的22端口
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
# 将服务端的指定域名的请求转发到本地7000端口
[web]
type = http
local_port = 7000
custom_domains = <你的域名>启动
1
./frpc -c ./frpc.ini
启动输出如下
1
2
3
42020/02/23 19:19:34 [I] [service.go:250] [ae46f3632a860bba] login to server success, get run id [ae46f3632a860bba], server udp port [0]
2020/02/23 19:19:34 [I] [proxy_manager.go:144] [ae46f3632a860bba] proxy added: [web ssh]
2020/02/23 19:19:34 [I] [control.go:164] [ae46f3632a860bba] [web] start proxy success
2020/02/23 19:19:34 [I] [control.go:164] [ae46f3632a860bba] [ssh] start proxy success同时观察服务端输出,增加了如下输出
1
2
3
4
52020/02/23 19:19:34 [I] [service.go:392] [ae46f3632a860bba] client login info: ip [113.110.200.14:46946] version [0.31.2] hostname [] os [linux] arch [arm]
2020/02/23 19:19:34 [I] [http.go:92] [ae46f3632a860bba] [web] http proxy listen for host [xxx.xxx.xxx] location [] group []
2020/02/23 19:19:34 [I] [control.go:445] [ae46f3632a860bba] new proxy [web] success
2020/02/23 19:19:34 [I] [tcp.go:63] [ae46f3632a860bba] [ssh] tcp proxy listen port [6000]
2020/02/23 19:19:34 [I] [control.go:445] [ae46f3632a860bba] new proxy [ssh] success至此,通过ssh命令登录VPS的6000端口,即可远程访问到树莓派;通过指定的域名,即可访问到树莓派中暴露于7000端口的web服务。
验证
测试需求一
1
2# 尝试远程ssh登录
ssh -oPort=6000 pi@<VPS公网IP>ssh登录成功
1
2
3
4floyd@floyd-ThinkPad-T490:~$ ssh -oPort=6000 [email protected]
The authenticity of host '[blog]:6000 ([xxx.xxx.xxx.xxx]:6000)' can't be established.
ECDSA key fingerprint is SHA256:o4+aSfAmCMmE5l/UAj+8/XJ8YyWDYrMzlbVelu0ggAA.
Are you sure you want to continue connecting (yes/no)?测试需求二
浏览器访问指定域名,成功访问到树莓派中运行的服务——AWTRIX控制台
总结
通过frp,完美实现了上述两个需求,关键是免费。当然,该软件还有更加强大的功能,如有需要,尽管去折腾。
在配置过程中也有遇到坑和觉得可以改善的地方,如下
VPS安全组问题。阿里云的访问白名单默认没有开启6000\7000\7001三个端口的访问,需要手动添加,否则无法访问
服务端可客户端的启动脚本,可以加入开机自启动。为了方便,服务端使用了supervisor进行管理。客户端则直接添加到/etc/rc.local
服务端
supervisor配置文件
1
2
3
4
5
6
7
8
9
10
11
12[program:frp]
directory = /root/frp/frp_0.31.2_linux_amd64
command = /root/frp/frp_0.31.2_linux_amd64/frps -c /root/frp/frp_0.31.2_linux_amd64/frps.ini
autostart = true
startsecs = 10
autorestart = true
startretries = 3
user = root
redirect_stderr = true
stdout_logfile_maxbytes = 50MB
stdout_logfile_backups = 20
stdout_logfile = /var/log/frp/frp.log1
2# 更新supervisor
supervisorctl update客户端
在/etc/systemd/system下创建frp.service文件,内容如下
1
2
3
4
5
6
7
8
9
10
11[Unit]
Description=FRP Client
After=network.target
[Service]
Type=simple
WorkingDirectory=/home/pi/frp/frp_0.31.2_linux_arm
ExecStart=/home/pi/frp/frp_0.31.2_linux_arm/frpc -c /home/pi/frp/frp_0.31.2_linux_arm/frpc.ini
[Install]
WantedBy=multi-user.target执行命令如下
1
2
3
4# 自启动开启
sudo systemctl enable frp.service
# 启动服务
sudo systemctl start frp.service